package com.jg.poiet;

import com.jg.poiet.config.Configure;
import com.jg.poiet.exception.ResolverException;
import com.jg.poiet.render.RenderFactory;
import com.jg.poiet.resolver.TemplateVisitor;
import com.jg.poiet.template.ElementTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Constructor;
import java.util.List;

/**
 * 模板
 */
public class ExcelTemplate implements Closeable {

    private static Logger logger = LoggerFactory.getLogger(ExcelTemplate.class);

    private AbstractNiceWorkbook workbook;
    private Configure config;
    private List<ElementTemplate> eleTemplates;

    public List<ElementTemplate> getEleTemplates() {
        // 解析模板和模板元素
        if(eleTemplates==null){
            TemplateVisitor visitor = new TemplateVisitor(config);
            this.eleTemplates = visitor.visitExcel(this.getWorkbook().getWorkbook());
        }
        return eleTemplates;
    }

    protected ExcelTemplate(AbstractNiceWorkbook abstractNiceWorkbook, Configure config)
    {
        this.workbook = abstractNiceWorkbook;
        this.config = config;
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,String filePath) {
        return compile(excelTypeClass,new File(filePath));
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,File file) {
        return compile(excelTypeClass,file, Configure.createDefault());
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,InputStream inputStream) {
        return compile(excelTypeClass,inputStream, Configure.createDefault());
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,String filePath, Configure config) {
        return compile(excelTypeClass,new File(filePath), config);
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,File file, Configure config) {
        try {
            return compile(excelTypeClass,new FileInputStream(file), config);
        } catch (FileNotFoundException e) {
            logger.error("Cannot find the file", e);
            throw new ResolverException("Cannot find the file [" + file.getPath() + "]");
        }
    }

    public static ExcelTemplate compile(Class<? extends AbstractNiceWorkbook> excelTypeClass,InputStream inputStream, Configure config) {
        try {
            Constructor<? extends AbstractNiceWorkbook> constructor = excelTypeClass.getConstructor(InputStream.class);
            ExcelTemplate instance = new ExcelTemplate(constructor.newInstance(inputStream),config);
            return instance;
        } catch (Exception e) {
            logger.error("Compile template failed", e);
            throw new ResolverException("Compile template failed");
        }
    }
    public ExcelTemplate render(Object model) {
        RenderFactory.getRender(model,config.getElMode()).render(this);
        return this;
    }

    public void write(OutputStream out) throws IOException {
        this.workbook.write(out);
    }

    public void writeToFile(String path) throws IOException {
        this.workbook.writeToFile(path);
    }
    @Override
    public void close() throws IOException {
        this.workbook.close();
    }

    public AbstractNiceWorkbook getWorkbook() {
        return this.workbook;
    }

    public Configure getConfig() {
        return config;
    }

}
